function [w,d,wwwwd,dy] = date2gpsw(datec,opt)
%
%[W,D,WWWWD,DY] = date2gpsw(DATEC)
%
% Computes the GPS week W, the corresponding GPS day number D, the string 
% WWWWD (4-digit week number and day number, which can be used to generate 
% file names) and the annual progressive day (starting from January, 1) DY 
% for the input date DATEC. 
% The input variable DATEC can be:
%   - a N-length column-vector of numbers (in this case, DATEC(k) is a 
%     MATLAB serial date number;
%   - a N-by-11 (N-by-10 if all days are lower than 10) char array such 
%     that DATEC(k) is a string in the form dd-mmm-yyyy (e.g. 12-Dec-2007) 
%     or a N-by-7 char array where DATEC(k) is a string YYMMMDD (e.g.
%     07DEC12);  
%   - a N-by-3 matrix where DATEC(k) is a date vector (e.g.[2007 12 12]).
%     If DATEC is a matrix with more than three columns, DATEC(:,4:end)
%     is ignored.
% The outputs W, D and DY are column vectors and WWWWD is a N-by-5 char 
% array. For example, if DATEC is '12-Dec-2007', it is W = 1460, D = 0,
% WWWWD = 14600 and DY = 354 (the first day of a week, i.e. Sunday, is 0, 
% the last, i.e. Saturnday, is 6).
% GPS time was born at midnight between 5-Jan-1980 and 6-Jan-1980 (note
% that 6-Jan-1980 was a Sunday). If DATEC is 6-Jan-1980, the outputs W = 0, 
% D = 0 and DY = 6 are provided. If DATEC preceeds 6-Jan-1980, whichever 
% is the used notation, an error message is provided.
%
%[W,D,WWWWD,DY] = date2gpsw(DATEC,OPT)
%
% If OPT is empty or zero, the function operates as above. If OPT is
% non-empty and non-zero, if DATEC is before the birth date of the GPS 
% calendar, the outputs W = NaN, D = NaN, WWWWD = 'NNNNN' and DY = NaN 
% are provided togheter with a warning message instead of the error 
% message. In this way, gpsweek can be called by another function without 
% risk of execution interruption.
% For example, if DATEC is the matrix 
%
%       2008 10 2
%       2008 10 3
%       1958 10 4
%       2008 10 5
%
% where the rows 1, 2 and 4 have valid data whereas the row 3 not, if OPT
% is lacking, empty or zero, no results are provided (error case). With 
% the same input data, if OPT is non-empty and non-zero, the results are 
% the columns-vectors:
%
%       [W,D,WWWWD,DY]  = [ 1499   4    '14994'   276
%                           1499   5    '14995'   277
%                           NaN   NaN   'NNNNN'   NaN 
%                           1500  1500  '15000'   279 ];
%
% See also gpsw2serial, MJD2frac, frac2MJD, serial2frac, frac2serial,
% serial2YMD. 

% G. Teza, 2008, 2021

if nargin == 1
    opt = []; 
end
if opt == 0
    opt = []; 
end

if ischar(datec)    % case of string-type date
    if size(datec,2) == 7
        yy = datec(:,1:2);
        yyn = str2num(yy); %#ok<ST2NM> 
        I1 = yyn >= 80;
        I2 = yyn <  80;
        yyn(I1) = 1900+yyn(I1);
        yyn(I2) = 2000+yyn(I2);
        yyyy = num2str(yyn);
        mm = datec(:,3:5);
        dd = datec(:,6:7);
        eldash = repelem('-',size(datec,1))';   % to allow horzcat with dash
        datec = [dd eldash mm eldash yyyy];
    end
    daten = datenum(datec); 
else                % case of numeric-type date 
    ncol = size(datec,2);
    if ncol > 1     % case of vector-type date (input matrix) 
        daten = datenum(datec(:,1:3));
    else            % case of Matlab serial number date 
        daten = datec;
    end
end

dater = datenum(1980,1,6);       % reference (first GPS week)

Ino = daten < dater;
if sum(Ino) > 0 && isempty(opt)
    error('%s is not a valid GPS date',datestr(daten(Ino(1))));
end

% initializations:
N = length(daten);
w = nan(N,1); 
d = nan(N,1); 
dy = nan(N,1);
wwwwd = repmat('N',N,5);

% computations:
dd = daten-dater;
Iyes = dd >= 0;
w(Iyes) = floor(dd(Iyes)/7);
d(Iyes) = rem(dd(Iyes),7);
[yydy,~,~] = datevec(daten);
datei = datenum([yydy ones(N,2)]);
dy(Iyes) = daten(Iyes)-datei(Iyes)+1;

for k = 1:N
    if Iyes(k)
        wk = w(k);
        wsk = num2str(wk);
        if wk < 10
            wsck = ['000' wsk];
        elseif wk < 100
            wsck = ['00' wsk];
        elseif wk < 1000
            wsck = ['0' wsk];
        else
            wsck = wsk;
        end
        wwwwd(k,:) = [wsck num2str(d(k))];
    else   % case of invalid date (here, opt is surely true)
        msg_inv = sprintf('%s is not a valid GPS date\n',datestr(daten(k)));
        fprintf('Warning: %s\n',msg_inv);
    end
end